package com.clp.protocol.iec104.apdu.asdu.infoobj.infoelem;

import com.clp.protocol.iec104.definition.TypeTag;
import com.clp.protocol.core.pdu.nbytepdu.BaseNBytePduClip;
import com.clp.protocol.iec104.apdu.asdu.infoobj.TypeTagRequired;

/**
 * 信息元素
 */
public abstract class InfoElem extends BaseNBytePduClip<InfoElem> implements TypeTagRequired {
    private final TypeTag typeTag;

    protected InfoElem(TypeTag typeTag) {
        this.typeTag = typeTag;
    }

    @Override
    public TypeTag typeTag() {
        return typeTag;
    }

    public boolean isTaInfoElem() {
        return this instanceof TaInfoElem;
    }

    public TaInfoElem castToTaInfoElem() {
        return this.castTo(TaInfoElem.class);
    }

    public boolean isTsInfoElem() {
        return this instanceof TsInfoElem;
    }

    public TsInfoElem castToTsInfoElem() {
        return this.castTo(TsInfoElem.class);
    }

    public boolean isTcInfoElem() {
        return this instanceof TcInfoElem;
    }

    public TcInfoElem castToTcInfoElem() {
        return this.castTo(TcInfoElem.class);
    }

    public boolean isTmInfoElem() {
        return this instanceof TmInfoElem;
    }

    public TmInfoElem castToTmInfoElem() {
        return this.castTo(TmInfoElem.class);
    }

    /**
     * 将自身转化为自身的子类对象
     *
     * @param clazz
     * @param <T>
     * @return
     */
    @SuppressWarnings("unchecked")
    public <T extends InfoElem> T castTo(Class<T> clazz) {
        if (clazz.isAssignableFrom(this.getClass())) {
            return (T) this;
        }
        throw new ClassCastException(this.getClass().getName() + "不存在子类" + clazz.getName() + ", 类型转换失败！");
    }
}
